import os
import sys
import traceback
from pathlib import Path

# 首先设置FFmpeg路径和解决导入问题
def setup_environment():
    try:
        # 设置FFmpeg路径
        if hasattr(sys, '_MEIPASS'):
            # 打包后的环境
            base_path = sys._MEIPASS
            ffmpeg_path = os.path.join(base_path, 'ffmpeg')
        else:
            # 开发环境
            base_path = os.path.dirname(os.path.abspath(__file__))
            ffmpeg_path = os.path.join(base_path, 'ffmpeg')
        
        # 添加到系统PATH
        if os.path.exists(ffmpeg_path) and ffmpeg_path not in os.environ['PATH']:
            os.environ['PATH'] = ffmpeg_path + os.pathsep + os.environ['PATH']
        
        # 设置pydub的ffmpeg路径
        ffmpeg_exe = os.path.join(ffmpeg_path, 'ffmpeg.exe')
        ffprobe_exe = os.path.join(ffmpeg_path, 'ffprobe.exe')
        
        if os.path.exists(ffmpeg_exe):
            os.environ['FFMPEG_PATH'] = ffmpeg_exe
        
    except Exception as e:
        print(f"环境设置错误: {e}")

# 立即执行环境设置
setup_environment()

# 现在导入其他模块
try:
    from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                                 QPushButton, QLabel, QLineEdit, QFileDialog, QProgressBar,
                                 QSpinBox, QGroupBox, QCheckBox, QMessageBox, QTextEdit,
                                 QListWidget, QListWidgetItem, QSplitter, QFrame, QSizePolicy,
                                 QTabWidget, QDoubleSpinBox, QComboBox)
    from PyQt5.QtCore import Qt, QThread, pyqtSignal
    from PyQt5.QtGui import QFont, QIcon
    import pydub
    from pydub import AudioSegment
except ImportError as e:
    print(f"导入模块失败: {e}")
    print("请安装所需依赖: pip install PyQt5 pydub")
    input("按回车键退出...")
    sys.exit(1)

class AudioProcessorThread(QThread):
    """音频处理线程"""
    progress_signal = pyqtSignal(int, str)
    finished_signal = pyqtSignal(int, int)
    
    def __init__(self, input_files, output_dir, silence_duration, volume_change, volume_unit, is_batch_mode=True, process_type="silence"):
        super().__init__()
        self.input_files = input_files  # 可以是文件列表或目录路径
        self.output_dir = output_dir
        self.silence_duration = silence_duration
        self.volume_change = volume_change  # 音量变化值
        self.volume_unit = volume_unit  # 音量单位 ("dB" 或 "%")
        self.is_batch_mode = is_batch_mode  # True:批量模式, False:单个文件模式
        self.process_type = process_type  # "silence"或"volume"
        self.stop_flag = False
        
    def run(self):
        try:
            os.makedirs(self.output_dir, exist_ok=True)
            
            processed_count = 0
            error_count = 0
            
            if self.is_batch_mode:
                # 批量模式：input_files是目录路径
                input_dir = self.input_files
                files_to_process = []
                
                for filename in os.listdir(input_dir):
                    file_ext = os.path.splitext(filename.lower())[1]
                    if file_ext in ['.wav', '.mp3']:
                        files_to_process.append(os.path.join(input_dir, filename))
            else:
                # 单个文件模式：input_files是文件路径列表
                files_to_process = self.input_files
            
            total_files = len(files_to_process)
            
            if total_files == 0:
                self.progress_signal.emit(0, "没有找到符合条件的音频文件")
                self.finished_signal.emit(0, 0)
                return
            
            for i, input_path in enumerate(files_to_process):
                if self.stop_flag:
                    break
                
                filename = os.path.basename(input_path)
                output_path = os.path.join(self.output_dir, filename)
                
                self.progress_signal.emit(
                    int((i / total_files) * 100),
                    f"正在处理: {filename}"
                )
                
                try:
                    # 读取音频文件
                    if input_path.lower().endswith('.wav'):
                        audio = AudioSegment.from_wav(input_path)
                    elif input_path.lower().endswith('.mp3'):
                        audio = AudioSegment.from_mp3(input_path)
                    else:
                        error_count += 1
                        continue
                    
                    if self.process_type == "silence":
                        # 创建静音段
                        silence = AudioSegment.silent(
                            duration=self.silence_duration,
                            frame_rate=audio.frame_rate
                        )
                        
                        # 合并静音和原音频
                        processed_audio = silence + audio
                    elif self.process_type == "volume":
                        # 调整音量
                        if self.volume_unit == "dB":
                            # 使用dB直接调整
                            processed_audio = audio + self.volume_change
                        else:
                            # 使用百分比调整
                            processed_audio = audio.apply_gain(self.volume_change)
                    
                    # 导出文件，保持原音频参数
                    if output_path.lower().endswith('.wav'):
                        processed_audio.export(
                            output_path,
                            format='wav'
                        )
                    elif output_path.lower().endswith('.mp3'):
                        processed_audio.export(
                            output_path,
                            format='mp3',
                            bitrate="192k"  # 使用固定比特率避免问题
                        )
                    
                    processed_count += 1
                    
                except Exception as e:
                    error_count += 1
                    error_msg = f"处理失败: {filename} - {str(e)}"
                    self.progress_signal.emit(
                        int((i / total_files) * 100),
                        error_msg
                    )
            
            self.finished_signal.emit(processed_count, error_count)
            
        except Exception as e:
            error_msg = f"处理过程中发生错误: {str(e)}"
            self.progress_signal.emit(0, error_msg)
            self.finished_signal.emit(0, 1)
    
    def stop(self):
        self.stop_flag = True

class AudioSilenceAdderGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.process_thread = None
        self.selected_files = []  # 存储单个选择的文件
        self.init_ui()
        
    def init_ui(self):
        self.setWindowTitle("音频处理工具 v1.2 - 支持静音添加和音量调整   作者：赵文昱 tda")
        self.setGeometry(100, 100, 900, 600)
        
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QHBoxLayout(central_widget)
        
        # 左侧：文件选择区域
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        
        # 模式选择标签
        mode_label = QLabel("处理模式选择")
        mode_label.setFont(QFont("Arial", 8, QFont.Normal))
        left_layout.addWidget(mode_label)
        
        # 创建选项卡
        self.tab_widget = QTabWidget()
        
        # 静音添加选项卡
        self.silence_tab = QWidget()
        self.setup_silence_tab()
        self.tab_widget.addTab(self.silence_tab, "添加静音")
        
        # 音量调整选项卡
        self.volume_tab = QWidget()
        self.setup_volume_tab()
        self.tab_widget.addTab(self.volume_tab, "调整音量")
        
        left_layout.addWidget(self.tab_widget)
        
        # 输出目录设置
        output_group = QGroupBox("输出设置")
        output_layout = QVBoxLayout()
        
        output_path_layout = QHBoxLayout()
        self.output_path_edit = QLineEdit()
        self.output_path_edit.setPlaceholderText("请选择输出目录...")
        output_browse_btn = QPushButton("浏览")
        output_browse_btn.clicked.connect(self.browse_output)
        output_path_layout.addWidget(self.output_path_edit)
        output_path_layout.addWidget(output_browse_btn)
        output_layout.addLayout(output_path_layout)
        
        output_group.setLayout(output_layout)
        left_layout.addWidget(output_group)
        
        # 处理按钮
        button_layout = QHBoxLayout()
        self.batch_start_btn = QPushButton("开始批量处理")
        self.batch_start_btn.clicked.connect(self.start_processing)
        self.single_start_btn = QPushButton("开始单个处理")
        self.single_start_btn.clicked.connect(self.start_processing)
        self.stop_btn = QPushButton("停止处理")
        self.stop_btn.clicked.connect(self.stop_processing)
        self.stop_btn.setEnabled(False)
        
        button_layout.addWidget(self.batch_start_btn)
        button_layout.addWidget(self.single_start_btn)
        button_layout.addWidget(self.stop_btn)
        left_layout.addLayout(button_layout)
        
        left_layout.addStretch()
        
        # 右侧：进度显示区域
        right_widget = QWidget()
        right_layout = QVBoxLayout(right_widget)
        
        # 进度显示
        progress_group = QGroupBox("处理进度")
        progress_layout = QVBoxLayout()
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        progress_layout.addWidget(self.progress_bar)
        
        self.status_label = QLabel("就绪")
        progress_layout.addWidget(self.status_label)
        
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        progress_layout.addWidget(self.log_text)
        
        progress_group.setLayout(progress_layout)
        right_layout.addWidget(progress_group)
        
        # 添加到主布局
        main_layout.addWidget(left_widget, 1)
        main_layout.addWidget(right_widget, 1)
        
    def setup_silence_tab(self):
        layout = QVBoxLayout(self.silence_tab)
        
        # 批量模式设置
        batch_group = QGroupBox("批量处理模式")
        batch_layout = QVBoxLayout()
        
        batch_path_layout = QHBoxLayout()
        self.batch_input_edit = QLineEdit()
        self.batch_input_edit.setPlaceholderText("请选择输入目录...")
        batch_browse_btn = QPushButton("选择目录")
        batch_browse_btn.clicked.connect(self.browse_batch_input)
        batch_path_layout.addWidget(self.batch_input_edit)
        batch_path_layout.addWidget(batch_browse_btn)
        batch_layout.addLayout(batch_path_layout)
        
        batch_group.setLayout(batch_layout)
        layout.addWidget(batch_group)
        
        # 单个文件模式设置
        single_group = QGroupBox("单个文件处理模式")
        single_layout = QVBoxLayout()
        
        # 文件列表
        self.file_list = QListWidget()
        self.file_list.setMaximumHeight(150)
        single_layout.addWidget(QLabel("已选文件:"))
        single_layout.addWidget(self.file_list)
        
        # 文件操作按钮
        file_btn_layout = QHBoxLayout()
        add_file_btn = QPushButton("添加文件")
        add_file_btn.clicked.connect(self.add_single_files)
        remove_file_btn = QPushButton("移除选中")
        remove_file_btn.clicked.connect(self.remove_selected_files)
        clear_files_btn = QPushButton("清空列表")
        clear_files_btn.clicked.connect(self.clear_file_list)
        
        file_btn_layout.addWidget(add_file_btn)
        file_btn_layout.addWidget(remove_file_btn)
        file_btn_layout.addWidget(clear_files_btn)
        single_layout.addLayout(file_btn_layout)
        
        single_group.setLayout(single_layout)
        layout.addWidget(single_group)
        
        # 参数设置
        params_group = QGroupBox("处理参数")
        params_layout = QVBoxLayout()
        
        # 静音时长
        duration_layout = QHBoxLayout()
        duration_layout.addWidget(QLabel("静音时长:"))
        self.duration_spin = QSpinBox()
        self.duration_spin.setRange(100, 60000)
        self.duration_spin.setValue(3000)
        self.duration_spin.setSuffix(" ms")
        duration_layout.addWidget(self.duration_spin)
        duration_layout.addStretch()
        params_layout.addLayout(duration_layout)
        
        # 提示信息
        tip_label = QLabel("提示: 静音时长范围为100-60000毫秒")
        tip_label.setStyleSheet("color: #999; font-size: 16px;")
        params_layout.addWidget(tip_label)
        
        # 文件格式选择（仅批量模式有效）
        format_layout = QHBoxLayout()
        format_layout.addWidget(QLabel("处理格式:"))
        self.wav_checkbox = QCheckBox("WAV")
        self.wav_checkbox.setChecked(True)
        self.mp3_checkbox = QCheckBox("MP3")
        self.mp3_checkbox.setChecked(True)
        format_layout.addWidget(self.wav_checkbox)
        format_layout.addWidget(self.mp3_checkbox)
        format_layout.addStretch()
        params_layout.addLayout(format_layout)
        
        params_group.setLayout(params_layout)
        layout.addWidget(params_group)
        
    def setup_volume_tab(self):
        layout = QVBoxLayout(self.volume_tab)
        
        # 批量模式设置
        batch_group = QGroupBox("批量处理模式")
        batch_layout = QVBoxLayout()
        
        batch_path_layout = QHBoxLayout()
        self.volume_batch_input_edit = QLineEdit()
        self.volume_batch_input_edit.setPlaceholderText("请选择输入目录...")
        volume_batch_browse_btn = QPushButton("选择目录")
        volume_batch_browse_btn.clicked.connect(self.browse_volume_batch_input)
        batch_path_layout.addWidget(self.volume_batch_input_edit)
        batch_path_layout.addWidget(volume_batch_browse_btn)
        batch_layout.addLayout(batch_path_layout)
        
        batch_group.setLayout(batch_layout)
        layout.addWidget(batch_group)
        
        # 单个文件模式设置
        single_group = QGroupBox("单个文件处理模式")
        single_layout = QVBoxLayout()
        
        # 文件列表
        self.volume_file_list = QListWidget()
        self.volume_file_list.setMaximumHeight(150)
        single_layout.addWidget(QLabel("已选文件:"))
        single_layout.addWidget(self.volume_file_list)
        
        # 文件操作按钮
        file_btn_layout = QHBoxLayout()
        add_file_btn = QPushButton("添加文件")
        add_file_btn.clicked.connect(self.add_volume_single_files)
        remove_file_btn = QPushButton("移除选中")
        remove_file_btn.clicked.connect(self.remove_volume_selected_files)
        clear_files_btn = QPushButton("清空列表")
        clear_files_btn.clicked.connect(self.clear_volume_file_list)
        
        file_btn_layout.addWidget(add_file_btn)
        file_btn_layout.addWidget(remove_file_btn)
        file_btn_layout.addWidget(clear_files_btn)
        single_layout.addLayout(file_btn_layout)
        
        single_group.setLayout(single_layout)
        layout.addWidget(single_group)
        
        # 参数设置
        params_group = QGroupBox("处理参数")
        params_layout = QVBoxLayout()
        
        # 音量调整单位和值
        volume_control_layout = QHBoxLayout()
        volume_control_layout.addWidget(QLabel("音量调整:"))
        
        self.volume_spin = QDoubleSpinBox()
        self.volume_spin.setRange(-50.0, 50.0)
        self.volume_spin.setValue(0.0)
        self.volume_spin.setSingleStep(1.0)
        volume_control_layout.addWidget(self.volume_spin)
        
        self.volume_unit_combo = QComboBox()
        self.volume_unit_combo.addItems(["dB", "%"])
        self.volume_unit_combo.currentTextChanged.connect(self.on_volume_unit_changed)
        volume_control_layout.addWidget(self.volume_unit_combo)
        
        volume_control_layout.addStretch()
        params_layout.addLayout(volume_control_layout)
        
        # 提示信息
        self.volume_tip_label = QLabel("提示: dB范围: -50dB 到 +50dB (0dB表示原音量)")
        self.volume_tip_label.setStyleSheet("color: #999; font-size: 16px;")
        params_layout.addWidget(self.volume_tip_label)
        
        # 文件格式选择（仅批量模式有效）
        format_layout = QHBoxLayout()
        format_layout.addWidget(QLabel("处理格式:"))
        self.volume_wav_checkbox = QCheckBox("WAV")
        self.volume_wav_checkbox.setChecked(True)
        self.volume_mp3_checkbox = QCheckBox("MP3")
        self.volume_mp3_checkbox.setChecked(True)
        format_layout.addWidget(self.volume_wav_checkbox)
        format_layout.addWidget(self.volume_mp3_checkbox)
        format_layout.addStretch()
        params_layout.addLayout(format_layout)
        
        params_group.setLayout(params_layout)
        layout.addWidget(params_group)
        
    def on_volume_unit_changed(self, unit):
        if unit == "dB":
            self.volume_spin.setRange(-50.0, 50.0)
            self.volume_spin.setValue(0.0)
            self.volume_spin.setSingleStep(1.0)
            self.volume_tip_label.setText("提示: dB范围: -50dB 到 +50dB (0dB表示原音量)")
        else:  # %
            self.volume_spin.setRange(1.0, 500.0)
            self.volume_spin.setValue(100.0)
            self.volume_spin.setSingleStep(10.0)
            self.volume_tip_label.setText("提示: 百分比范围: 1% 到 500% (100%表示原音量)")
            
    def browse_batch_input(self):
        directory = QFileDialog.getExistingDirectory(self, "选择批量处理目录")
        if directory:
            self.batch_input_edit.setText(directory)
            
    def browse_volume_batch_input(self):
        directory = QFileDialog.getExistingDirectory(self, "选择批量处理目录")
        if directory:
            self.volume_batch_input_edit.setText(directory)
            
    def add_single_files(self):
        files, _ = QFileDialog.getOpenFileNames(
            self, 
            "选择音频文件", 
            "", 
            "音频文件 (*.wav *.mp3);;所有文件 (*)"
        )
        if files:
            for file in files:
                if file not in self.selected_files:
                    self.selected_files.append(file)
                    item = QListWidgetItem(os.path.basename(file))
                    item.setToolTip(file)  # 存储完整路径
                    self.file_list.addItem(item)
            
            self.log_text.append(f"已添加 {len(files)} 个文件")
            
    def add_volume_single_files(self):
        files, _ = QFileDialog.getOpenFileNames(
            self, 
            "选择音频文件", 
            "", 
            "音频文件 (*.wav *.mp3);;所有文件 (*)"
        )
        if files:
            for file in files:
                if file not in self.selected_files:
                    self.selected_files.append(file)
                    item = QListWidgetItem(os.path.basename(file))
                    item.setToolTip(file)  # 存储完整路径
                    self.volume_file_list.addItem(item)
            
            self.log_text.append(f"已添加 {len(files)} 个文件")
            
    def remove_selected_files(self):
        selected_items = self.file_list.selectedItems()
        for item in selected_items:
            file_path = item.toolTip()
            if file_path in self.selected_files:
                self.selected_files.remove(file_path)
            self.file_list.takeItem(self.file_list.row(item))
            
    def remove_volume_selected_files(self):
        selected_items = self.volume_file_list.selectedItems()
        for item in selected_items:
            file_path = item.toolTip()
            if file_path in self.selected_files:
                self.selected_files.remove(file_path)
            self.volume_file_list.takeItem(self.volume_file_list.row(item))
            
    def clear_file_list(self):
        self.file_list.clear()
        self.selected_files = []
        self.log_text.append("已清空文件列表")
            
    def clear_volume_file_list(self):
        self.volume_file_list.clear()
        self.selected_files = []
        self.log_text.append("已清空文件列表")
            
    def browse_output(self):
        directory = QFileDialog.getExistingDirectory(self, "选择输出目录")
        if directory:
            self.output_path_edit.setText(directory)
            
    def get_selected_formats(self, process_type):
        formats = []
        if process_type == "silence":
            if self.wav_checkbox.isChecked():
                formats.append('.wav')
            if self.mp3_checkbox.isChecked():
                formats.append('.mp3')
        else:  # volume
            if self.volume_wav_checkbox.isChecked():
                formats.append('.wav')
            if self.volume_mp3_checkbox.isChecked():
                formats.append('.mp3')
        return formats
            
    def start_processing(self):
        output_dir = self.output_path_edit.text().strip()
        
        if not output_dir:
            QMessageBox.warning(self, "警告", "请选择输出目录！")
            return
        
        current_tab = self.tab_widget.currentIndex()
        is_batch_mode = self.sender() == self.batch_start_btn
        
        if current_tab == 0:  # 静音添加选项卡
            process_type = "silence"
            silence_duration = self.duration_spin.value()
            volume_change = 0  # 不使用
            volume_unit = "dB"  # 不使用
            
            if is_batch_mode:
                input_dir = self.batch_input_edit.text().strip()
                if not input_dir:
                    QMessageBox.warning(self, "警告", "请选择输入目录！")
                    return
                    
                if not os.path.exists(input_dir):
                    QMessageBox.warning(self, "警告", "输入目录不存在！")
                    return
                    
                # 检查目录中是否有音频文件
                has_files = False
                formats = self.get_selected_formats(process_type)
                for filename in os.listdir(input_dir):
                    if os.path.splitext(filename.lower())[1] in formats:
                        has_files = True
                        break
                        
                if not has_files:
                    QMessageBox.warning(self, "警告", "输入目录中没有找到指定格式的音频文件！")
                    return
                    
                input_files = input_dir
                self.log_text.append(f"开始批量添加静音，输入目录: {input_dir}")
                
            else:
                if not self.selected_files:
                    QMessageBox.warning(self, "警告", "请至少添加一个音频文件！")
                    return
                    
                input_files = self.selected_files
                self.log_text.append(f"开始单个添加静音，共 {len(self.selected_files)} 个文件")
                
        else:  # 音量调整选项卡
            process_type = "volume"
            silence_duration = 0  # 不使用
            volume_change = self.volume_spin.value()
            volume_unit = self.volume_unit_combo.currentText()
            
            # 百分比模式需要特殊处理
            if volume_unit == "%":
                # 将百分比转换为增益值 (100% = 0dB, 200% = +6dB, 50% = -6dB)
                volume_change = 20 * (volume_change / 100.0).log10() if volume_change > 0 else -60
            
            if is_batch_mode:
                input_dir = self.volume_batch_input_edit.text().strip()
                if not input_dir:
                    QMessageBox.warning(self, "警告", "请选择输入目录！")
                    return
                    
                if not os.path.exists(input_dir):
                    QMessageBox.warning(self, "警告", "输入目录不存在！")
                    return
                    
                # 检查目录中是否有音频文件
                has_files = False
                formats = self.get_selected_formats(process_type)
                for filename in os.listdir(input_dir):
                    if os.path.splitext(filename.lower())[1] in formats:
                        has_files = True
                        break
                        
                if not has_files:
                    QMessageBox.warning(self, "警告", "输入目录中没有找到指定格式的音频文件！")
                    return
                    
                input_files = input_dir
                self.log_text.append(f"开始批量调整音量，输入目录: {input_dir}")
                
            else:
                if not self.selected_files:
                    QMessageBox.warning(self, "警告", "请至少添加一个音频文件！")
                    return
                    
                input_files = self.selected_files
                self.log_text.append(f"开始单个调整音量，共 {len(self.selected_files)} 个文件")
        
        # 禁用按钮
        self.batch_start_btn.setEnabled(False)
        self.single_start_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)
        self.log_text.clear()
        
        self.process_thread = AudioProcessorThread(
            input_files, output_dir, silence_duration, volume_change, volume_unit, is_batch_mode, process_type
        )
        self.process_thread.progress_signal.connect(self.update_progress)
        self.process_thread.finished_signal.connect(self.processing_finished)
        self.process_thread.start()
        
    def stop_processing(self):
        if self.process_thread and self.process_thread.isRunning():
            self.process_thread.stop()
            self.process_thread.wait()
            self.status_label.setText("处理已停止")
            self.log_text.append("处理已停止")
            
        self.batch_start_btn.setEnabled(True)
        self.single_start_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        
    def update_progress(self, progress, message):
        self.progress_bar.setValue(progress)
        self.status_label.setText(message)
        self.log_text.append(message)
        
    def processing_finished(self, processed_count, error_count):
        self.progress_bar.setValue(100)
        result_text = f"处理完成！成功: {processed_count}, 失败: {error_count}"
        self.status_label.setText(result_text)
        self.log_text.append(result_text)
        
        self.batch_start_btn.setEnabled(True)
        self.single_start_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        
        if processed_count > 0:
            QMessageBox.information(self, "完成", 
                                  f"处理完成！\n成功: {processed_count} 个文件\n失败: {error_count} 个文件")
        
    def closeEvent(self, event):
        if self.process_thread and self.process_thread.isRunning():
            self.process_thread.stop()
            self.process_thread.wait()
        event.accept()

def main():
    app = QApplication(sys.argv)
    window = AudioSilenceAdderGUI()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()